package com.woniuxy.sales.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;

import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.sales.common.RedisConst;
import com.woniuxy.sales.common.enumeration.BusinessCode;
import com.woniuxy.sales.common.enumeration.OrderStatus;
import com.woniuxy.sales.config.AlipayConfig;
import com.woniuxy.sales.mapper.AddressMapper;
import com.woniuxy.sales.mapper.OrderDetailsMapper;
import com.woniuxy.sales.model.entity.*;
import com.woniuxy.sales.model.vo.CartItemVo;
import com.woniuxy.sales.model.vo.CartVo;
import com.woniuxy.sales.model.vo.OrderItemVo;
import com.woniuxy.sales.model.vo.OrderVo;
import com.woniuxy.sales.service.GoodsService;
import com.woniuxy.sales.service.OrderDetailsService;
import com.woniuxy.sales.service.OrdersService;
import com.woniuxy.sales.mapper.OrdersMapper;
import com.woniuxy.sales.untils.Assert;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 【订单表】
 */
@Service
@Slf4j
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders>
        implements OrdersService {

    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private AddressMapper addressMapper;
    @Autowired
    private OrderDetailsService orderDetailsService;
    @Autowired
    private OrderDetailsMapper orderDetailsMapper;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private AlipayClient alipayClient;
    @Autowired
    private AlipayConfig alipayConfig;

    @Override
    public List<OrderVo> queryOrder(Integer userId, Integer status) {
        LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<>();
        //查询某个用户的订单
        wrapper.eq(Orders::getUserId, userId);
        //如果不为0，则查询指定状态的订单
        if (status != 0) {
            wrapper.eq(Orders::getOrderStatus, status);
        }
        //按下单时间倒序排列
        wrapper.orderByDesc(Orders::getOrderDate);
        List<Orders> orders = ordersMapper.selectList(wrapper);

        //将订单对象，转换为订单视图对象
        List<OrderVo> orderVos = orders.stream().map(order -> {
            //复制订单对象的属性到OrderVo对象中
            OrderVo orderVo = BeanUtil.copyProperties(order, OrderVo.class);
            //查询地址对象//查询地址 address 表 返回结果 xx
            Address address= addressMapper.selectById(order.getAddressId());
            if (address != null){
                orderVo.setReceiver(address.getReceiver());
                orderVo.setTelephone(address.getTelephone());
                orderVo.setAddress(address.getAllAddress());
            }
            //订单明细
            LambdaQueryWrapper<OrderDetails> queryWrapper= Wrappers.lambdaQuery(OrderDetails.class)
                    .eq(OrderDetails::getOrderId,order.getOrderId());
            List<OrderDetails> orderDetails = orderDetailsMapper.selectList(queryWrapper);
            //订单明细转成订单项视图对象
            List<OrderItemVo> itemVos= orderDetails.stream().map(orderDetail -> {
                OrderItemVo itemVo= BeanUtil.copyProperties(orderDetail,OrderItemVo.class);
                Goods goods = goodsService.findById(orderDetail.getProductId());
                itemVo.setPrice(goods.getPrice());
                itemVo.setImgSrc(goods.getImgSrc());
                itemVo.setName(goods.getName());
                return itemVo ;
            }).collect(Collectors.toList());
            //添加到订单的属性中
            orderVo.setOrderItem(itemVos);
            return orderVo;
        }).collect(Collectors.toList());
        return orderVos;
    }

    @Override
    @Transactional  //开启事务，因为有多个插入操作
    public String createOrder(Integer userId, Integer addressId) {
        //1、生成订单对象（生产订单编号）
        Long orderId = IdUtil.getSnowflake(1, 1).nextId();
        //2、获取用户的购物车对象
        CartVo cartvo = (CartVo) redisTemplate.opsForValue().get(RedisConst.USER_CART_PREFIX + ":" + userId);
        //3、遍历购物车判断每本书的库存是否充足
        HashOperations ops = redisTemplate.opsForHash();
        for (CartItemVo cartItem : cartvo.getItemList()) {
            //获取这本书籍的库存
            Integer storeCount = (Integer) ops.get(RedisConst.GOOD_STORAGE, cartItem.getGoodsId().toString());
            //库存量小于购买量，应该返回：库存不足
            Assert.error(storeCount < cartItem.getQuantity(), BusinessCode.STORAGE_NOT_ENOUGH);
            //库存量是充足的，扣减Redis的库存 (加上负数)
            ops.increment(RedisConst.GOOD_STORAGE, cartItem.getGoodsId().toString(), -cartItem.getQuantity());
            //每个购物车项是一个订单项
            //4、生成订单项
            OrderDetails orderDetails = new OrderDetails();
            orderDetails.setOrderId(orderId);  //雪花算法生成，外键
            orderDetails.setProductId(cartItem.getGoodsId());
            orderDetails.setPrice(cartItem.getPrice());
            orderDetails.setQuantity(cartItem.getQuantity());
            orderDetails.setSumPrice(cartItem.getSumPrice());
            //写到数据库中
            orderDetailsMapper.insert(orderDetails);
        }
        //5、创建订单对象
        Orders orders = new Orders();
        orders.setOrderId(orderId);  //主键
        orders.setUserId(userId); //用户id
        orders.setOrderDate(new Date());
        orders.setTotalPrice(cartvo.getTotalPrice());   //总价格
        orders.setAddressId(addressId);  //地址id
        orders.setOrderStatus(OrderStatus.NO_PAY.getCode());  //待付款
        //写到数据库中
        ordersMapper.insert(orders);
        log.info("订单创建成功，订单号：{}", orderId);
        //返回订单号
        return orderId.toString();

    }

    @Override
    @Transactional
    public String pay(Long orderId) {
        log.info("获取到的参数是：{}",orderId);
        //通过id查询订单
        Orders order = ordersMapper.selectById(orderId);
        log.info("数据库中查询到的数据为：{}",order);
        //创建交易页面的支付请求对象
        AlipayTradePagePayRequest request= getAlipayTradePagePayRequest(order);
        String form;
        try {
            //调用SDK生成表单
            form = alipayClient.pageExecute(request).getBody();
            log.info("支付宝支付表单：" + form);
        } catch (AlipayApiException e) {
            e.printStackTrace();
            //让事务回滚
            throw new RuntimeException(e.getMessage());
        }
        //返回表单给控制器
        return form;
    }

    @Override
    public void updateOrderStatus(Long orderId, Integer orderStatus) {
        //通过订单号查询订单
        Orders order=getById(orderId);
        order.setOrderStatus(orderStatus);
        // 更新订单
        ordersMapper.updateById(order);
        //2. 修改数据库库存
        //2.1. 查询订单明细
        LambdaQueryWrapper<OrderDetails> wrapper=Wrappers.lambdaQuery(OrderDetails.class).eq(OrderDetails::getOrderId,orderId);
        List<OrderDetails> orderDetails = orderDetailsService.list(wrapper);
        //2.2. 遍历：获取每一个商品修改库存store_count减
        for (OrderDetails orderDetail : orderDetails){
          updateGoodStoreCount(orderDetail);
        }
    }

    @Override
    public void updateGoodStoreCount(OrderDetails orderDetail) {
            //更新商品
       Goods good=goodsService.getById(orderDetail.getProductId());
            // 修改库存 = 库存 - 购买数量
        good.setStoreCount(good.getStoreCount()-orderDetail.getQuantity());
            // 更新商品
        goodsService.updateById(good);
    }

    /**
     * 创建交易页面的支付请求对象
     */
    private AlipayTradePagePayRequest getAlipayTradePagePayRequest(Orders order) {
        log.info("获取到订单：{}",order);
        //1.准备支付的参数，包括需要支付的订单的id，价格，物品名称
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();
        model.setOutTradeNo(order.getOrderId().toString()); // 需要支付的订单id，自定义的订单id，不能重复，唯一，已经支付的无法继续支付
        model.setTotalAmount(order.getTotalPrice().toString()); // 需要支付的钱 model.setTotalAmount("88.88");
        model.setSubject("汽车相关商品"); // 要支付的物品，比如 model.setSubject("Iphone6 16G");
        model.setProductCode("FAST_INSTANT_TRADE_PAY");  //销售产品码，电脑支付场景就使用FAST_INSTANT_TRADE_PAY

        // 2.创建支付的请求，设置上面的准备支付的参数
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setBizModel(model);

        // 3.设置支付宝异步回调，这个需要用内网穿透
        request.setNotifyUrl(alipayConfig.getNotifyUrl());

        // 4.设置支付宝支付成功返回的页面，这里让支付成功直接回到static下的一个静态页面中
        request.setReturnUrl(alipayConfig.getReturnUrl());
        return request;
    }

    @Override
    @Transactional
    public void cancelOrder(Long orderId, Integer userId) {
        // 1. 查询订单
        Orders order = ordersMapper.selectById(orderId);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }

        // 2. 校验订单的状态
        if (order.getOrderStatus() == OrderStatus.ALREADY_CANCEL.getCode()) {
            throw new RuntimeException("订单已经被取消");
        }
        if (order.getOrderStatus() == OrderStatus.PAID.getCode()) {
            throw new RuntimeException("订单已支付，无法取消");
        }

        // 3. 修改订单状态为已取消
        order.setOrderStatus(OrderStatus.ALREADY_CANCEL.getCode());
        ordersMapper.updateById(order);

//        // 4. 处理订单项，回滚商品库存
//        LambdaQueryWrapper<OrderDetails> wrapper = Wrappers.lambdaQuery(OrderDetails.class).eq(OrderDetails::getOrderId, orderId);
//        List<OrderDetails> orderDetailsList = orderDetailsMapper.selectList(wrapper);
//        for (OrderDetails orderDetail : orderDetailsList) {
//            // 回滚库存
//            restoreGoodsStoreCount(orderDetail);
//        }

        // 5. 如果订单已支付，需要通过支付平台进行退款处理（例如支付宝）
        if (order.getOrderStatus() == OrderStatus.PAID.getCode()) {
            refundPayment(orderId);
        }

        log.info("订单已取消，订单号：{}", orderId);
    }

    private void restoreGoodsStoreCount(OrderDetails orderDetail) {
        Goods good = goodsService.getById(orderDetail.getProductId());
        if (good != null) {
            good.setStoreCount(good.getStoreCount() + orderDetail.getQuantity());
            goodsService.updateById(good);
            log.info("商品库存已恢复，商品ID：{}, 当前库存：{}", good.getId(), good.getStoreCount());
        }
    }
    private void refundPayment (Long orderId){
        Orders order = ordersMapper.selectById(orderId);

        // 创建退款请求对象
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(order.getOrderId().toString());  // 订单号
        model.setRefundAmount(order.getTotalPrice().toString());  // 退款金额

        request.setBizModel(model);

        try {
            AlipayTradeRefundResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                log.info("退款成功，订单号：{}", orderId);
            } else {
                log.error("退款失败，订单号：{}", orderId);
            }
        } catch (AlipayApiException e) {
            log.error("退款过程中发生错误，订单号：{}", orderId, e);
            throw new RuntimeException("退款失败");
        }
    }

    @Override //根据选中项生成订单
    @Transactional  //开启事务，因为有多个插入操作
    public String createBySelection(Integer userId, List<CartItemVo> cartItemVos, Integer addressId, Double totalPrice) {
        //1、生成订单对象（生产订单编号）
        Long orderId = IdUtil.getSnowflake(1, 1).nextId();

        //3、遍历购物车判断每本书的库存是否充足
        HashOperations ops = redisTemplate.opsForHash();
        for (CartItemVo cartItem : cartItemVos) {
            //获取这本书籍的库存
            Integer storeCount = (Integer) ops.get(RedisConst.GOOD_STORAGE, cartItem.getGoodsId().toString());
            //库存量小于购买量，应该返回：库存不足
            Assert.error(storeCount < cartItem.getQuantity(), BusinessCode.STORAGE_NOT_ENOUGH);
            //库存量是充足的，扣减Redis的库存 (加上负数)
            ops.increment(RedisConst.GOOD_STORAGE, cartItem.getGoodsId().toString(), -cartItem.getQuantity());
            //每个购物车项是一个订单项
            //4、生成订单项
            OrderDetails orderDetails = new OrderDetails();
            orderDetails.setOrderId(orderId);  //雪花算法生成，外键
            orderDetails.setProductId(cartItem.getGoodsId());
            orderDetails.setPrice(cartItem.getPrice());
            orderDetails.setQuantity(cartItem.getQuantity());
            orderDetails.setSumPrice(cartItem.getSumPrice());
            //写到数据库中
            orderDetailsMapper.insert(orderDetails);
        }
        //5、创建订单对象
        Orders orders = new Orders();
        orders.setOrderId(orderId);  //主键
        orders.setUserId(userId); //用户id
        orders.setOrderDate(new Date());
        orders.setTotalPrice(totalPrice);   //总价格
        orders.setAddressId(addressId);  //地址id
        orders.setOrderStatus(OrderStatus.NO_PAY.getCode());  //待付款
        //写到数据库中
        ordersMapper.insert(orders);
        log.info("订单创建成功，订单号：{}", orderId);
        //返回订单号
        return orderId.toString();
    }

    @Override //立即购买的生成订单
    @Transactional  //开启事务，因为有多个插入操作
    public String createByBuy(Integer userId, CartItemVo cartItemVo, Integer addressId) {
        //1、生成订单对象（生产订单编号）
        Long orderId = IdUtil.getSnowflake(1, 1).nextId();
        //3、判断每本书的库存是否充足
        HashOperations ops = redisTemplate.opsForHash();
        //获取这本书籍的库存
        Integer storeCount = (Integer) ops.get(RedisConst.GOOD_STORAGE, cartItemVo.getGoodsId().toString());
        //库存量小于购买量，应该返回：库存不足
        Assert.error(storeCount < cartItemVo.getQuantity(), BusinessCode.STORAGE_NOT_ENOUGH);
        //库存量是充足的，扣减Redis的库存 (加上负数)
        ops.increment(RedisConst.GOOD_STORAGE, cartItemVo.getGoodsId().toString(), -cartItemVo.getQuantity());
        //4、生成订单项
        OrderDetails orderDetails = new OrderDetails();
        orderDetails.setOrderId(orderId);  //雪花算法生成，外键
        orderDetails.setProductId(cartItemVo.getGoodsId());
        orderDetails.setPrice(cartItemVo.getPrice());
        orderDetails.setQuantity(cartItemVo.getQuantity());
        orderDetails.setSumPrice(cartItemVo.getSumPrice());
        //写到数据库中
        orderDetailsMapper.insert(orderDetails);
        //5、创建订单对象
        Orders orders = new Orders();
        orders.setOrderId(orderId);  //主键
        orders.setUserId(userId); //用户id
        orders.setOrderDate(new Date());
        orders.setTotalPrice(cartItemVo.getSumPrice());   //总价格
        orders.setAddressId(addressId);  //地址id
        orders.setOrderStatus(OrderStatus.NO_PAY.getCode());  //待付款
        //写到数据库中
        ordersMapper.insert(orders);
        log.info("订单创建成功，订单号：{}", orderId);
        //返回订单号
        return orderId.toString();
    }




}




